package com.guoxin.mashibing.executor;

import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.*;

/**
 * @author guoxin
 * @date 2019/7/12
 */
public class ForkJoinPoolTest {
    private static final int MAX_SIZE = 50000;
    private static final Random R = new Random(14);
    private static final int[] NUMS = new int[1000000];

    static {
        for (int i = 0; i < NUMS.length; i++) {
            NUMS[i] = R.nextInt(100);
        }
        Optional.of("总和为：" + Arrays.stream(NUMS).sum()).ifPresent(System.out::println);
    }


    public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
//        AddTask at = new AddTask(NUMS.length);
        AddTask2 at = new AddTask2(NUMS.length);
        ForkJoinPool fjp = new ForkJoinPool();
//        fjp.execute(at);
        ForkJoinTask<Long> fjt = fjp.submit(at);
        Long sum = fjt.get();
        System.out.println(sum);
//        System.in.read();
    }


    private static class AddTask extends RecursiveAction {

        private int start;
        private int end;

        AddTask(int s, int e) {
            this.start = s;
            this.end = e;
        }

        AddTask(int e) {
            this(0, e);
        }

        @Override
        protected void compute() {
            if (end - start <= MAX_SIZE) {
                long sum = 0L;
                for (int i = start; i < end; i++) {
                    sum = sum + NUMS[i];
                }
                Optional.of("from:" + start + " to:" + end + " = " + sum).ifPresent(System.out::println);
            } else {
                int middle = start + (end - start) / 2;
                AddTask task1 = new AddTask(start, middle);
                AddTask task2 = new AddTask(middle, end);
                task1.fork();
                task2.fork();

            }
        }
    }

    private static class AddTask2 extends RecursiveTask<Long> {

        private int start;
        private int end;

        AddTask2(int s, int e) {
            this.start = s;
            this.end = e;
        }

        AddTask2(int e) {
            this(0, e);
        }

        @Override
        protected Long compute() {
            if (end - start <= MAX_SIZE) {
                long sum = 0L;
                for (int i = start; i < end; i++) {
                    sum = sum + NUMS[i];
                }
                return sum;
            }
            int middle = start + (end - start) / 2;
            AddTask2 task1 = new AddTask2(start, middle);
            AddTask2 task2 = new AddTask2(middle, end);
            task1.fork();
            task2.fork();

            return task1.join() + task2.join();
        }
    }
}
